package com.apes.fn.scm.contract;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.merchant.account.model.MerchantAccountSettlement;
import com.apes.fn.scm.merchant.account.repository.AccountSettlementRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Creator: zouyc
 * CreateDate: 2019-12-10 16:09
 * Description:
 **/
@Service("fnContrastService")
public class FnContrastService extends DomainService {
    @Autowired
    FnContractRepository fnContractRepository;

    @Autowired
    private AccountSettlementRepository settlementRepository;

    /**
     * 新增
     *
     * @param request
     * @return
     */
    public FnContract create(SimpleRequest request) {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("create");
        fnContract.setCreator(this.getPersonId(request));
        if (fnContract.getValidFrom().after(fnContract.getValidPeriod()) || fnContract.getValidFrom().equals(fnContract.getValidPeriod())) {
            throw new RuntimeException("有效期止日期应大于有效期起日期");
        }

        List<FnContract> fnContracts = fnContractRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "company.id", "EQ", fnContract.getCompany().getId(),
                "partner.id", "EQ", fnContract.getPartner().getId(), "state", "EQ", "approve"));

        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(fnContracts, fnContract.getValidFrom());
        Boolean end = checkPartnerCheckDate(fnContracts, fnContract.getValidPeriod());

        if (start || end){
            throw new RuntimeException("赋能公司已存在相同有效期的赋能合同,请确认!");
        }
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 修改
     *
     * @param request
     * @return
     */
    public FnContract update(SimpleRequest request) throws Exception {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("create");
        if (fnContract.getValidFrom().after(fnContract.getValidPeriod()) || fnContract.getValidFrom().equals(fnContract.getValidPeriod())) {
            throw new RuntimeException("有效期止日期应大于有效期起日期");
        }

        List<FnContract> fnContracts = fnContractRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "id", "NE", fnContract.getId(),
                "company.id", "EQ", fnContract.getCompany().getId(),
                "partner.id", "EQ", fnContract.getPartner().getId(), "state", "EQ", "approve"));

        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(fnContracts, fnContract.getValidFrom());
        Boolean end = checkPartnerCheckDate(fnContracts, fnContract.getValidPeriod());

        if (start || end){
            throw new RuntimeException("赋能公司已存在相同有效期的赋能合同,请确认!");
        }
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 审核
     *
     * @param request
     * @return
     */
    public FnContract approve(SimpleRequest request) {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("approve");
        fnContract.setApproveDate(new Date());
        fnContract.setApproveUid(this.getPerson(request));
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 终止
     *
     * @param request
     * @return
     */
    public FnContract repeal(SimpleRequest request) {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("repeal");
        fnContract.setRepealDate(new Date());
        fnContract.setRepealUid(this.getPerson(request));
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 延期
     *
     * @param request
     * @return
     */
    public FnContract extension(SimpleRequest request) throws Exception {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("extension");
        fnContract.setExtensionUid(this.getPerson(request));
        fnContract.setExtensionDate(new Date());
        if (fnContract.getValidFrom().after(fnContract.getValidPeriod()) || fnContract.getValidFrom().equals(fnContract.getValidPeriod())) {
            throw new RuntimeException("有效期止日期应大于有效期起日期");
        }

        List<FnContract> fnContracts = fnContractRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "id", "NE", fnContract.getId(),
                "company.id", "EQ", fnContract.getCompany().getId(),
                "partner.id", "EQ", fnContract.getPartner().getId(), "state", "EQ", "approve"));

        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(fnContracts, fnContract.getValidFrom());
        Boolean end = checkPartnerCheckDate(fnContracts, fnContract.getValidPeriod());

        if (start || end){
            throw new RuntimeException("赋能公司已存在相同有效期的赋能合同,请确认!");
        }
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 检查时间是否在政策期起止起止内
     * @param partnerChecks
     * @param reconcileDate
     */
    private Boolean checkPartnerCheckDate(List<FnContract> partnerChecks, Date reconcileDate){
        AtomicBoolean flag = new AtomicBoolean(false);
        if (!CollectionUtils.isEmpty(partnerChecks)){
            try {
                partnerChecks.forEach(item -> {
                    boolean belongCalendar = DateUtil.belongCalendar(reconcileDate,
                            DateUtil.dateToDate(item.getValidFrom(), DateUtil.SHOW_DATE_FORMAT),
                            DateUtil.dateToDate(item.getValidPeriod(), DateUtil.SHOW_DATE_FORMAT));
                    if (belongCalendar){
                        flag.set(true);
                        throw new RuntimeException("终止forEach循环,减少无意义比较");
                    }
                });
            }catch (Exception e){}
        }
        return flag.get();
    }

    /**
     * 激活
     *
     * @param request
     * @return
     */
    public FnContract activation(SimpleRequest request) throws Exception {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("create");
        fnContract.setActivationUid(this.getPerson(request));
        fnContract.setActivationDate(new Date());
        return fnContractRepository.saveAndFlush(fnContract);
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        FnContract fnContract = request.getO(FnContract.class);
        fnContract.setState("delete");
        fnContract.setDeleteDate(new Date());
        fnContract.setDeleteUid(getPerson(request));
        fnContractRepository.save(fnContract);
        return "删除成功";
    }

    public List<FnContract> findByFnCustomer(SimpleRequest request) {
        List<FnContract> list = null;
        list = fnContractRepository.findAll(JpaDsl.toCriteriaByEq("partner.id", request.get("fnCustomer")));
        return list;
    }

    //获取审核后的赋能合同
    public List<FnContract> findByFnCustomerSh(SimpleRequest request) {
        List<FnContract> list = null;
        list = fnContractRepository.findAll(JpaDsl.toCriteriaByEq("partner.id", request.get("partner"), "state", "approve"));
        if (list.size() == 0) {
            throw new RuntimeException("获取赋能合同失败，请检查选择的商户是否定义赋能商务合同！");
        }
        return list;
    }

    @Listener(topic = "event:fn.contract.findFirstValidFnContractCompanyByPartnerId")
    public String findFirstValidFnContractCompanyByPartnerId(SimpleRequest request) {
        List<FnContract> fnContracts = fnContractRepository.qryValidFnContract(request.get("partnerId"));
        return fnContracts.isEmpty() ? "" : fnContracts.stream().findFirst().get().getCompany().getId();
    }

    /**
     * 检查公司是否和1007有赋能合同
     *
     * @param request
     * @return
     */
    public boolean checkFnCompany(SimpleRequest request) {
        List<FnContract> all = fnContractRepository.findAll(JpaDsl.toCriteria(
                "state", "EQ", "approve",
                "company.id", "EQ", "1007",
                "partner.id", "EQ", request.get("companyId").toString(),
                "validPeriod", "GT", new Date()
        ));
        if (all.size() == 0) return false;
        return true;
    }

    /**
     * 对账单2.0商户获取合同
     *
     * @param request
     * @return
     */
    public Map findByPartner(SimpleRequest request) {
        List<Map> mapList = new ArrayList<>();
        String partner = request.get("key");
        List<FnContract> fnContractList = fnContractRepository.findByPartner(request.get("key"), partner);
        if (fnContractList.size() < 1) throw new RuntimeException("商户" + partner + "无有效合同，请重新定义！");
        List<MerchantAccountSettlement> byMaxReconcileEndDate = settlementRepository.findByMaxReconcileEndDate(partner);
        String finalDate = null;
        if (byMaxReconcileEndDate.size() > 0) {
            Date date = DateUtil.add(byMaxReconcileEndDate.get(0).getReconcileEndDate(), Calendar.DAY_OF_MONTH, 1);
            finalDate = DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT);
        }

        String finalDate1 = finalDate;
        fnContractList.forEach(fnContract -> {
            mapList.add(MapUtil.mapper("id", fnContract.getPartner().getId(), "name", fnContract.getPartner().getName(),
                    "company", fnContract.getCompany(), "fnContract", fnContract, "reconcileBeginDate", finalDate1));
        });
        return MapUtil.mapper("content", mapList);
    }

    /**
     * 查询平台公司（根据赋能公司）
     *
     * @param request
     * @return
     */
    public PartyRole findCompanyByPartner(SimpleRequest request) {
        PartyRole partner = request.getO(PartyRole.class);
        FnContract fnContract = fnContractRepository.findAll(JpaDsl.toCriteria("partner.id", "EQ", partner.getId(),
                "state", "EQ", "approve",
                "validPeriod", "LTE", new Date())).stream().findFirst().orElse(null);
        // 查询不到合同默认为1007
        return fnContract == null ? SpringManager.getBean(PartyRoleRepository.class).findOne("1007") : fnContract.getCompany();
    }

    /**
     * 查询平台公司（根据赋能公司）
     *
     * @param request
     * @return1007
     */
    public Object findPartner(SimpleRequest request) {
        JSONObject group = (JSONObject) request.getJO().get("group");
        JSONObject jsonObject = checkRequest((List<Map>) group.get("filters"));

        if (jsonObject.get("id").toString().equals("")) return null;
        List<FnContract> fnContracts = fnContractRepository.findPartner(jsonObject.get("id").toString(), jsonObject.get("company").toString());

        //将赋能公司提取存放
        List<PartyRole> partyRoles = new ArrayList<>();
        fnContracts.forEach(v -> {
            partyRoles.add(v.getPartner());
        });
        return new PageImpl<>(partyRoles, PageRequest.of(request.get("page"), request.get("size")), partyRoles.size());
    }

    /**
     * 查询平台公司（根据赋能公司）
     *
     * @param request
     * @return1007
     */
    public FnContract findByCompanyAndState(SimpleRequest request) {
        if (request.get("company").toString().equals("")) return null;
        FnContract FnContract = fnContractRepository.findByPartnerAndState(request.get("company").toString());
        if(Objects.isNull(FnContract)) throw new RuntimeException(request.get("company").toString() + "该公司无有效赋能合同，找不到缴款平台账户，请联系对账组确认！");
        return FnContract;
    }


    /**
     * 查询平台公司（根据赋能公司）
     *
     * @param request
     * @return1007
     */
    public String findByCompany(SimpleRequest request) {
        if (request.get("company").toString().equals("")) return null;
        FnContract FnContract = fnContractRepository.findByPartnerAndState(request.get("company").toString());
        if(Objects.isNull(FnContract)) throw new RuntimeException(request.get("company").toString() + "该公司无有效赋能合同，找不到缴款平台账户，请联系对账组确认！");
        return FnContract.getCompany().getId();
    }
    /**
     * 获取赋能合同列表
     * @param request
     * @return
     */
    public JSONObject queryList(SimpleRequest request){
        JSONObject result = new JSONObject();

        return result;
    }

    /**
     * 解析前端参数
     *
     * @param filters
     * @return
     */
    public JSONObject checkRequest(List<Map> filters) {
        JSONObject model = new JSONObject();
        filters.forEach(filter -> {
            model.put((String) filter.get("field"), filter.get("value"));
        });
        return model;
    }
}
